package com.generate.run;

import com.generate.core.ColumnBean;
import com.generate.core.FreemarkerUtil;
import com.generate.core.TableBean;
import freemarker.template.Template;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class Generate {
    private static JdbcTemplate jdbcTemplate = (JdbcTemplate) new ClassPathXmlApplicationContext("applicationContext.xml").getBean("jdbcTemplate");

    /**
     * 数据库名
     */
    public static final String SCHEMA_NAME = "dts";

    /**
     * 输出路径绝对地址
     */
    public static final String OUTPUT_PATH = "d:/generate/";

    /**
     * 生成代码的package前缀
     */
    public static final String PACKAGE_BASE = "ops.sysdev.dts";

    /**
     * 生成类的前缀，如xxxSimpleDAO中的Simple
     */
    public static final String CLASS_PREFIX = "Simple";

    public static final String JDBC_TEMPLATE_NAME = "jdbcTemplate";

    public static List<TableBean> getTables() {
        List<TableBean> tableBeanList = jdbcTemplate.query("select * from tables where table_schema = ?", new Object[]{SCHEMA_NAME},
                new RowMapper<TableBean>() {
                    @Override
                    public TableBean mapRow(ResultSet rs, int rowNum) throws SQLException {
                        TableBean bean = new TableBean();
                        String tableName = rs.getString("table_name");
                        String tableNameTrimed = tableName;
                        if (tableName.startsWith("t_")) {
                            tableNameTrimed = tableName.substring(2);
                        }

                        bean.setTableName(tableName);
                        bean.setTableNameNoDash(delDash(tableNameTrimed));
                        bean.setTableNameCapitalized(StringUtils.capitalize(bean.getTableNameNoDash()));
                        bean.setTableComment(rs.getString("table_comment"));
                        return bean;
                    }
                });

        for (TableBean tableBean : tableBeanList) {
            tableBean.setColumnBeanList(getColumns(tableBean.getTableName(), tableBean));
        }

        return tableBeanList;
    }

    public static List<ColumnBean> getColumns(String tableName, final TableBean tableBean) {
        return jdbcTemplate.query("select * from COLUMNS where table_schema = ? and table_name = ?",
                new Object[]{SCHEMA_NAME, tableName},
                new RowMapper<ColumnBean>() {
                    @Override
                    public ColumnBean mapRow(ResultSet rs, int rowNum) throws SQLException {
                        ColumnBean bean = new ColumnBean();
                        String columnName = rs.getString("column_name");
                        bean.setColumnName(columnName);
                        bean.setColumnNameNoDash(delDash(columnName));
                        bean.setColumnNameCapitalized(StringUtils.capitalize(bean.getColumnNameNoDash()));

                        String charLength = rs.getString("CHARACTER_MAXIMUM_LENGTH");
                        if (StringUtils.isNotBlank(charLength)) {
                            bean.setLength(Integer.parseInt(charLength));
                        }

                        bean.setColumnComment(rs.getString("column_comment"));

                        String columnType = rs.getString("column_type").toLowerCase();
                        if (columnType.startsWith("varchar") || columnType.startsWith("char") || ("text").equals(columnType) || columnType.startsWith("enum")) {
                            bean.setColumnType("String");
                            bean.setColumnTypeRsGetter("getString");
                        } else if (columnType.startsWith("tinyint") || columnType.startsWith("smallint") || columnType.startsWith("mediumint")) {
                            bean.setColumnType("Integer");
                            bean.setColumnTypeRsGetter("getInt");
                        } else if (columnType.startsWith("int") || columnType.startsWith("bigint")) {
                            bean.setColumnType("Long");
                            bean.setColumnTypeRsGetter("getLong");
                        } else if (("timestamp").equals(columnType)) {
                            bean.setColumnType("Date");
                            bean.setColumnTypeRsGetter("getDate");
                            tableBean.setHasDateColumn(true);
                        } else if (columnType.startsWith("float")) {
                            bean.setColumnType("Float");
                            bean.setColumnTypeRsGetter("getFloat");
                        } else if (columnType.startsWith("double")) {
                            bean.setColumnType("Double");
                            bean.setColumnTypeRsGetter("getDouble");
                        } else if (columnType.startsWith("decimal")) {
                            bean.setColumnType("BigDecimal");
                            bean.setColumnTypeRsGetter("getBigDecimal");
                            tableBean.setHasBigDecimal(true);
                        } else {
                            throw new RuntimeException("Unsupported type: [" + columnType + "]!");
                        }

                        return bean;
                    }
                });
    }

    private static String delDash(String str) {
        String lowerCaseStr = str.toLowerCase();
        String[] noDashArray = StringUtils.split(lowerCaseStr, '_');
        StringBuilder noDash = new StringBuilder(noDashArray[0]);
        for (int i = 1; i < noDashArray.length; i++) {
            noDash.append(StringUtils.capitalize(noDashArray[i]));
        }
        return noDash.toString();
    }

    public static void main(String[] args) throws Exception {
        File outputPath = new File(OUTPUT_PATH);
        if (!outputPath.isDirectory()) {
            FileUtils.forceMkdir(outputPath);
        }

        String outputDirs = OUTPUT_PATH + "/" + StringUtils.replace(PACKAGE_BASE, ".", "/");

        List<TableBean> tableBeanList = getTables();
        for (TableBean tableBean : tableBeanList) {
            Map<String, Object> varMap = new HashMap<String, Object>();
            varMap.put("tableBean", tableBean);
            varMap.put("schemaName", SCHEMA_NAME);
            varMap.put("packageBase", PACKAGE_BASE);
            varMap.put("classPrefix", CLASS_PREFIX);
            varMap.put("jdbcTemplateName", JDBC_TEMPLATE_NAME);
            varMap.put("jdbcTemplateNameCapitalized", StringUtils.capitalize(JDBC_TEMPLATE_NAME));

            Template modelTemplate = FreemarkerUtil.getTemplate("template/model.ftl");
            FreemarkerUtil.outputProcessResult(outputDirs + "/model/" + tableBean.getTableNameCapitalized() + ".java", modelTemplate, varMap);

            Template daoTemplate = FreemarkerUtil.getTemplate("template/dao.ftl");
            FreemarkerUtil.outputProcessResult(outputDirs + "/dao/" + tableBean.getTableNameCapitalized() + CLASS_PREFIX + "DAO.java", daoTemplate, varMap);

            Template daoimplTemplate = FreemarkerUtil.getTemplate("template/daoimpl.ftl");
            FreemarkerUtil.outputProcessResult(outputDirs + "/dao/" + tableBean.getTableNameCapitalized() + CLASS_PREFIX + "DAOImpl.java", daoimplTemplate, varMap);

            Template serviceTemplate = FreemarkerUtil.getTemplate("template/service.ftl");
            FreemarkerUtil.outputProcessResult(outputDirs + "/service/" + tableBean.getTableNameCapitalized() + CLASS_PREFIX + "Service.java", serviceTemplate, varMap);

            Template serviceimplTemplate = FreemarkerUtil.getTemplate("template/serviceimpl.ftl");
            FreemarkerUtil.outputProcessResult(outputDirs + "/service/" + tableBean.getTableNameCapitalized() + CLASS_PREFIX + "ServiceImpl.java", serviceimplTemplate, varMap);
        }
    }
}
